#include "xrefsanalysis.h"

#include <module.h>

#include "console.h"
#include "xrefs.h"

XrefsAnalysis::XrefsAnalysis(duint base, duint size) : Analysis(base, size) {
  modbase = ModBaseFromAddr(base);
  modsize = ModSizeFromAddr(modbase);
}

void XrefsAnalysis::Analyse() {
  dputs("Starting xref analysis...");
  auto ticks = GetTickCount();

  for (auto addr = mBase; addr < mBase + mSize;) {
    if (!mCp.Disassemble(addr, translateAddr(addr))) {
      addr++;
      continue;
    }
    addr += mCp.Size();

    XREF xref;
    xref.addr = 0;
    xref.from = mCp.Address();
    for (auto i = 0; i < mCp.OpCount(); i++) {
      duint dest =
          mCp.ResolveOpValue(i, [](ZydisRegister) -> size_t { return 0; });
      if (inModRange(dest)) {
        xref.addr = dest;
        break;
      }
    }
    if (xref.addr) mXrefs.push_back(xref);
  }

  dprintf("%u xrefs found in %ums!\n", DWORD(mXrefs.size()),
          GetTickCount() - ticks);
}

void XrefsAnalysis::SetMarkers() {
  XrefDelRange(mBase, mBase + mSize - 1);
  for (const auto& xref : mXrefs) XrefAdd(xref.addr, xref.from);
}
